home *** CD-ROM | disk | FTP | other *** search
- /* CodeResource_Helper.c - some handy functions for this and that */
- /* Copyright not bothered with - this is pretty standard stuff. */
- #include "CodeResource.h"
- #include <stdlib.h>
-
- /* Resources */
- short OpenOrCreateResourceFork(StringPtr fileName);
- void DeleteAllExistingRsrcs(long theType, short theNum);
- /* Dialogs */
- void GetDlogOrigin (short dlogID, Point *where);
- Boolean GetAndAlignDialog(short resID);
- void FrameDialogItem(DialogPtr theDP,short theItem);
- void SetEText(DialogPtr dPtr, short theItem, StringPtr newStr);
- void GetEText(DialogPtr dPtr, short theItem, StringPtr currentStr);
- void SetCheck(DialogPtr dPtr, short chkItem, short zeroMeansNoCheck);
- void GetCheck(DialogPtr dPtr, short chkItem, Boolean *trueIfChecked);
- Handle GetButton(DialogPtr dPtr, short btnItem);
- void HiliteDlgControl(DialogPtr dPtr, short btnItem, short state);
- /* Pascal strings */
- void CopyPStr(Byte *srcStr, Byte *dstStr);
- void AppendPStr(Byte *s1, Byte *s2);
- Boolean PEqualStrs(Byte *aStr, Byte *bStr);
- /* Files, names and locations */
- Byte *FullPathNameFromDirectory(long DirID, short vRefNum, Byte *s);
- Byte *FullPathNameFromVRefNum(short vRefNum, Byte *s);
- short OpenWorkingDirectoryFromFullName(char *name, short len);
- /* Memory allocation */
- void InitTempCodeMemory(void);
- void *TMalloc(size_t size);
- void *Trealloc(void *ptr, size_t size);
- void Tfree(void *ptr);
- void TFreeAll(void);
- /* more memory allocation - faster, more efficient version */
- void *Fmalloc(register size_t nbytes);
- static void morecore(register short bucket);
- static void *true_get_memory(size_t size);
- void Ffree(void *cp);
- void *Frealloc(void *cp, size_t nbytes);
- static short findbucket(union overhead *freep, short srchlen);
- void FFreeAll(void);
- /* Misc */
- void NullOut(char *str, long nBytes);
- Boolean TaskWasInterrupted(void);
- Boolean CheckInWithCallingApp(void);
-
- /* Resources */
-
- /* Returns nonzero refnum if successful */
- short OpenOrCreateResourceFork(StringPtr fileName)
- {
- short refNum;
-
- if ((refNum = OpenResFile(fileName)) != -1 && refNum
- && ResError() == noErr) /* perfect paranoia */
- return(refNum);
- else
- {
- CreateResFile(fileName);
- if (ResError() != noErr)
- return(0);
- if ((refNum = OpenResFile(fileName)) != -1 && refNum
- && ResError() == noErr)
- return(refNum);
- }
- return(0);
- }
-
- /* Delete all instances of a particular resource.
- Call before creating each resource. */
- void DeleteAllExistingRsrcs(long theType, short theNum)
- {
- Handle rsrcHdle;
-
- while (rsrcHdle = Get1Resource(theType, theNum))
- {
- RmveResource(rsrcHdle);
- DisposHandle(rsrcHdle);
- }
- }
-
-
- /* Dialogs */
-
- void GetDlogOrigin (short dlogID, Point *where)
- {
- short screenWidth = GetScreenWidth();
- short screenHeight = GetScreenHeight();
- register DialogTHndl dlogHandle;
- register Rect * drp;
- register short dlogWidth, dlogHeight;
-
- /* Get a handle to the dialog */
- dlogHandle = (DialogTHndl) GetResource ('DLOG', dlogID);
-
- if (!dlogHandle)
- {
- SetPt (where, 85, 85);
- return;
- }
-
- /* get pointer to its bounding rectangle */
- drp = &((**dlogHandle).boundsRect);
-
- dlogWidth = drp->right - drp->left;
- dlogHeight = drp->bottom - drp->top;
-
- /* Calculate upper left corner that will leave box centered */
- where->h = (screenWidth - dlogWidth) >> 1;
- where->v = (screenHeight - dlogHeight) >> 1;
- }
-
-
- Boolean GetAndAlignDialog(short resID)
- {
- short sW,sH,dW,dH,left;
- Rect *drp;
- DialogTHndl dlogHandle;
- Boolean bigScreen;
-
- if (!GetResource('DLOG', resID)
- || !GetResource('DITL', resID)
- || ResError())
- {
- MemoryAlert();
- return(FALSE);
- }
- sW = GetScreenWidth();
- sH = GetScreenHeight();
- dlogHandle = (DialogTHndl) GetResource('DLOG', resID);
- drp = &((**dlogHandle).boundsRect);
- dW = drp->right - drp->left;
- dH = drp->bottom - drp->top;
- left = (sW - dW)>>1;
- /* all dialogs centered left-right */
- drp->left = left;
- drp->right = left + dW;
- /* vertical placement depends on screen size */
- if (sW >= 640 && sH >= 480)
- bigScreen = TRUE;
- else
- bigScreen = FALSE;
-
- if (bigScreen)
- {
- /* leave one-third of white at top */
- drp->top = (sH - dH) / 3;
- if (drp->top < 85)
- {
- if (drp->top < 40)
- drp->top = 40;
- if (sH <= 85 + dH)
- drp->top = 85;
- }
- }
- else if (sH <= 85 + dH)
- drp->top = 85;
- else
- drp->top = 40;
- drp->bottom = drp->top + dH;
- return(TRUE);
- }
-
- /* Place thick border around default item in a dialog */
- void FrameDialogItem(DialogPtr dPtr,short theItem)
- {
- GrafPtr savePort;
- PenState savePen;
- Handle h;
- Rect theBox;
- short theType, ovalSize;
-
- GetDItem(dPtr,theItem,&theType,&h,&theBox);
- GetPort(&savePort);
- SetPort(dPtr);
- GetPenState(&savePen);
- PenNormal();
- PenSize(2,2);
- InsetRect(&theBox,-3,-3);
- ovalSize = (theBox.bottom + 8 - theBox.top) / 2;
- FrameRoundRect(&theBox,ovalSize,ovalSize);
- SetPenState(&savePen);
- SetPort(savePort);
- }
-
- /* Set text content in a dialog edit field */
- void SetEText(DialogPtr dPtr, short theItem, StringPtr newStr)
- {
- short theType;
- Handle theItemH;
- Rect theBox;
-
- GetDItem(dPtr, theItem, &theType, &theItemH, &theBox);
- SetIText(theItemH, newStr);
- }
-
- /* Get current text in edit field - note storage for the string must
- be allocated by the calling function. */
- void GetEText(DialogPtr dPtr, short theItem, StringPtr currentStr)
- {
- short theType;
- Handle theItemH;
- Rect theBox;
-
- GetDItem(dPtr, theItem, &theType, &theItemH, &theBox);
- GetIText(theItemH, currentStr);
- }
-
- /* Set/clear check for check box or radio button, pass 0/1 or TRUE/FALSE . */
- void SetCheck(DialogPtr dPtr, short chkItem, short zeroMeansNoCheck)
- {
- short theType;
- Handle theItemH;
- Rect theBox;
-
- GetDItem(dPtr, chkItem, &theType, &theItemH, &theBox);
- SetCtlValue((ControlHandle)theItemH, zeroMeansNoCheck);
- }
-
- /* For check boxes and radio buttons, requires address of a Boolean from
- the call as in GetCheck(dPtr, 3, &myBoolean). */
- /* Usage tip, to toggle a box do
- GetCheck (dPtr, chkItem, &myBoolean);
- SetCheck (dPtr, chkItem, !myBoolean);
- */
- void GetCheck(DialogPtr dPtr, short chkItem, Boolean *trueIfChecked)
- {
- short theType;
- Handle theItemH;
- Rect theBox;
-
- GetDItem(dPtr, chkItem, &theType, &theItemH, &theBox);
- *trueIfChecked = (GetCtlValue((ControlHandle)theItemH) != 0);
- }
-
- /* Retrieve ControlHandle for button, in the form of a Handle */
- Handle GetButton(DialogPtr dPtr, short btnItem)
- {
- short theType;
- Handle theItem;
- Rect theBox;
-
- GetDItem(dPtr, btnItem, &theType, &theItem, &theBox);
- return(theItem);
- }
-
- /* Enable (state 0) or disable (state 255) a dialog control */
- void HiliteDlgControl(DialogPtr dPtr, short btnItem, short state)
- {
- ControlHandle theButton;
-
- theButton = (ControlHandle) GetButton(dPtr, btnItem);
- if ((**theButton).contrlHilite != state)
- HiliteControl (theButton, state);
- }
-
- /* Pascal strings */
-
- /* Copy one pascal string to another */
- void CopyPStr(Byte *srcStr, Byte *dstStr)
- {
- long srcLen = srcStr[0];
-
- BlockMove(srcStr, dstStr, srcLen + 1);
- }
-
- /* Append pascal s2 to pascal s1, avoiding overflow. */
- void AppendPStr(Byte *s1, Byte *s2)
- {
- short s1Len = s1[0];
- short s2Len = s2[0];
-
- if (s1Len + s2Len > 255)
- s2Len = 255 - s1Len;
-
- if (s2Len)
- {
- BlockMove (s2 + 1, s1 + s1Len + 1, s2Len);
- s1Len += s2Len;
- s1[0] = s1Len;
- }
- }
-
- Boolean PEqualStrs(Byte *aStr, Byte *bStr)
- {
- short i, lena = aStr[0], lenb = bStr[0];
-
- if (!lena || !lenb || lena != lenb)return(FALSE);
- for (i = 1; i <= lena; ++i)
- {
- if (aStr[i] != bStr[i])
- return(FALSE);
- }
- return(TRUE);
- }
-
- /* Files, names and locations */
-
- /* NOTE the following two functions are based on examples supplied
- by Apple on one of their DTS disks - error checking has been added,
- and these versions are independent of the signed vs unsigned char
- controversy surrounding str255. Byte is defined in MacTypes.h
- for THINK C v4. */
-
- /* Warning, these calls can fail! And why not? Everything else can... */
- /* Bug, these two are not for use by unix imitations. */
-
- /* Construct "\PDisk:folder1:folder2:...folderN:" where folderN
- contains the file of interest. */
- Byte *FullPathNameFromDirectory(long DirID, short vRefNum, Byte *s)
- {
- CInfoPBRec pb;
- Byte directoryName[256];
-
- s[0] = 0;
- pb.dirInfo.ioNamePtr = (StringPtr)directoryName;
- pb.dirInfo.ioDrParID = DirID;
-
- do
- {
- pb.dirInfo.ioVRefNum = vRefNum;
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
- if (PBGetCatInfo(&pb, FALSE))
- {
- break;
- }
- /* Append a colon */
- AppendPStr(directoryName, (Byte *)"\p:");
- AppendPStr(directoryName, s);
- CopyPStr(directoryName, s);
- } while (pb.dirInfo.ioDrDirID != 2);
- return(s);
- }
-
-
- Byte *FullPathNameFromVRefNum(short vRefNum, Byte *s)
- {
-
- WDPBRec pb;
-
- pb.ioNamePtr = NULL;
- pb.ioVRefNum = vRefNum;
- pb.ioWDIndex = 0;
- pb.ioWDProcID = 0;
-
- if (PBGetWDInfo(&pb,false))
- {
- s[0] = 0;
- return(s);
- }
- return(FullPathNameFromDirectory(pb.ioWDDirID,pb.ioWDVRefNum,s));
- }
-
- /* Determine working directory for file based on full path name. */
- short OpenWorkingDirectoryFromFullName(char *name, short len)
- {
- WDPBRec theParms;
- OSErr IOResult;
- char volname[256];
- extern void FileError(OSErr theFileErrorNum);
-
- volname[0] = len;
- BlockMove(name, volname+1, len);
-
- theParms.ioCompletion = NULL;
- theParms.ioVRefNum = 0;
- theParms.ioNamePtr = (StringPtr)volname;
- theParms.ioWDDirID = 2;
- theParms.ioWDProcID = 'ERIK';
- if (IOResult = PBOpenWD(&theParms, FALSE)) /* IM IV pg 158 */
- {
- OKStopAlert("Disk may not be on-line, \
- or file may have been moved, deleted, or renamed.");
- theParms.ioVRefNum = 0;
- }
- return(theParms.ioVRefNum);
- }
-
-
- /* Memory allocation */
- /* Preamble: at present, code resources fall into two camps; those
- that allocate a few chunks of memory via NewHandle, and those that
- allocate many chunks of memory via malloc. For the latter type,
- the following functions keep track of what memory was allocated,
- allowing it to be all freed at the end of a run with one call
- to TFreeAll().
-
- To use the functions TMalloc etc below instead of the standard malloc etc,
- place these lines in some header which is included in all your
- code resource files (see eg AWK.H), or at the top of each file:
-
- extern void *TMalloc(size_t size);
- extern void *Trealloc(void *ptr, size_t size);
- extern void Tfree(void *ptr);
-
- #define malloc(x) TMalloc(x)
- #define realloc(x, y) Trealloc(x, y)
- #define free(x) Tfree(x)
-
- - before firing up your code resource, call InitTempCodeMemory()
- - see eg InvokeHAWK() in hAWK_Interface.c
- -- and after your code resource is done, call TFreeAll()
- - see eg CleanUpAfterHAWK() in hAWK_Interface.c
- NOTE InitTempCodeMemory() is called whether using TMalloc() etc
- or Fmalloc() etc, BUT the FreeAll() functions are different
- -TFreeAll() for the former, FFreeAll() for the latter.
- */
-
-
- #ifdef malloc
- #undef malloc
- #undef realloc
- #undef free
- #endif malloc
-
- typedef struct MemoryLinks
- {
- struct MemoryLinks *next, *prev;
- short flags;
- }MemoryLinks;
-
- MemoryLinks THead;
- MemoryLinks *THeadPtr /* = {&THead, NULL}*/;
-
- void InitTempCodeMemory(void)
- {
- THeadPtr = &THead;
- THeadPtr->next = &THead;
- THeadPtr->prev = &THead;
- }
-
- /* Tracking versions of malloc, realloc, free - the T stands for temp */
- void *TMalloc(size_t size)
- {
- MemoryLinks *new, *old;
-
- size += sizeof(MemoryLinks);
- if (!(new = (MemoryLinks *)malloc(size)))
- return(NULL);
- old = THeadPtr->next; /* true next or THead itself */
- old->prev = new;
- new->next = old;
- new->prev = THeadPtr;
- THeadPtr->next = new;
- return((void *)(new + 1)); /* user doesn't "see" the links */
- }
-
- void *Trealloc(void *ptr, size_t size)
- {
- MemoryLinks *retPtr;
-
- if (!ptr)
- return(TMalloc(size));
- if (!size)
- {
- Tfree(ptr);
- return(NULL);
- }
- retPtr = ((MemoryLinks *)(ptr)) - 1;
- /* allocate MemoryLinks, too */
- size += sizeof(MemoryLinks);
- retPtr = (MemoryLinks *)realloc(retPtr, size);
- if (!retPtr) /* failure, but block is still there */
- return(NULL);
- (retPtr->prev)->next = (retPtr->next)->prev = retPtr;
- return((void *)(retPtr + 1));
- }
-
- void Tfree(void *ptr)
- {
- MemoryLinks *out;
-
- if (!ptr) return;
- out = ((MemoryLinks *)(ptr)) - 1;
- (out->next)->prev = out->prev;
- (out->prev)->next = out->next;
- free(out);
- }
-
- /* list wraps around */
- void TFreeAll(void)
- {
- MemoryLinks *dump = THeadPtr->next, *nextOne;
- #ifdef TMEMDEBUG
- long diff;
- char numStr[16];
- #endif
-
- while (dump != THeadPtr)
- {
- nextOne = dump->next;
- free(dump);
- dump = nextOne;
- }
- #ifdef TMEMDEBUG
- NumToString(malled, (StringPtr)numStr);
- PtoCstr(numStr);
- OKStopAlert("Total malloc'd:");
- OKStopAlert(numStr);
- NumToString(realled, (StringPtr)numStr);
- PtoCstr(numStr);
- OKStopAlert("Total realloc'd:");
- OKStopAlert(numStr);
-
- if (numfreedAtEnd + tfreeNum != tmallocNum)
- {
- diff = numfreedAtEnd + tfreeNum - tmallocNum;
- if (diff < 0L)
- {
- diff = -diff;
- NumToString(diff, (StringPtr)numStr);
- PtoCstr(numStr);
- OKStopAlert(numStr);
- }
- else /* very odd - more freed than allocated */
- {
- NumToString(diff, (StringPtr)numStr);
- PtoCstr(numStr);
- SysBeep(2);
- SysBeep(2);
- OKStopAlert(numStr);
- }
-
- }
- else
- {
- NumToString(tmallocNum, (StringPtr)numStr);
- PtoCstr(numStr);
- OKStopAlert("Num malloc calls total:");
- OKStopAlert(numStr);
- }
- #endif
- }
-
- /* more memory allocation - a more efficient (frugal) version */
-
- /* A frugal malloc, especially suited for allocating many many
- small blocks of memory. Currently used by hAWK, which is
- constantly allocating and freeing small blocks. Note TMalloc()
- above basically uses THINK C's malloc, which suffers from
- severe fragmentation problems. There is also more overhead with
- TMalloc (8 bytes vs 4 here).
- Memory is pre–allocated on demand for specific sizes only which
- are all powers of two (plus overhead). When you request a block
- of memory, your requested size is rounded up to the next power
- of two, and the request is satisfied from an array of similar-
- sized blocks. */
-
- /* Modified for the Mac and THINK C by Ken Earle.
- Based on Larry Wall’s modification (1989) of:
- * malloc.c (Caltech) 2/21/82
- * Chris Kingsley, kingsley@cit-20.
- *
- * This is a very fast storage allocator. It allocates blocks of a small
- * number of different sizes, and keeps free lists of each size. Blocks that
- * don't exactly fit are passed up to the next larger size. In this
- * implementation, the available sizes are 2^n-4 bytes long.
- * This is designed for use in a program that uses vast quantities of memory,
- * but bombs when it runs out.
-
- To use the functions Fmalloc etc below instead of the standard malloc etc,
- place these lines in some header which is included in all your
- code resource files (see eg AWK.H and CodeResHelper.h), or at
- the top of each file:
-
- extern void *Fmalloc(size_t size);
- extern void *Frealloc(void *ptr, size_t size);
- extern void Ffree(void *ptr);
-
- #define malloc(x) Fmalloc(x)
- #define realloc(x, y) Frealloc(x, y)
- #define free(x) Ffree(x)
-
- - before firing up your code resource, call InitTempCodeMemory()
- - see eg InvokeHAWK() in hAWK_Interface.c
- -- and after your code resource is done, call FFreeAll()
- - see eg CleanUpAfterHAWK() in hAWK_Interface.c
- NOTE InitTempCodeMemory() is called whether using TMalloc() etc
- or Fmalloc() etc, BUT the FreeAll() functions are different
- -TFreeAll() for the former, FFreeAll() for the latter.
- */
-
- #define u_char unsigned char
- #define u_int unsigned short
- #define u_short unsigned short
-
- /*
- * The overhead on a block is at least 4 bytes. When free, this space
- * contains a pointer to the next free block, and the bottom two bits must
- * be zero. When in use, the first byte is set to MAGIC, and the second
- * byte is the size index. The remaining bytes are for alignment.
- */
- union overhead {
- union overhead *ov_next; /* when free */
- struct {
- u_char ovu_magic; /* magic number */
- u_char ovu_index; /* bucket # */
- } ovu;
- };
- #define ov_magic ovu.ovu_magic
- #define ov_index ovu.ovu_index
-
- #define MAGIC 0xff /* magic # on accounting info */
-
- /*
- * nextf[i] is the pointer to the next free block of size 2^(i+3). The
- * smallest allocatable block is 8 bytes. The overhead information
- * precedes the data area returned to the user.
- */
- #define NBUCKETS 30
- static union overhead *nextf[NBUCKETS];
-
- #ifdef MSTATS
- /*
- * nmalloc[i] is the difference between the number of mallocs and frees
- * for a given block size.
- */
- static u_int nmalloc[NBUCKETS];
- #endif
-
- /* F stands for Frugal */
- void *Fmalloc(register size_t nbytes)
- {
- union overhead *p;
- short e, bucket;
-
- /*
- * Convert amount of memory requested into
- * closest block size stored in hash buckets
- * which satisfies request. Account for
- * space used per block for accounting.
- */
- --nbytes;
- if (nbytes < 1)
- nbytes = 1;
- e = 1;
- while (nbytes >>= 1)
- ++e;
- if (e <= 3)
- bucket = 0;
- else
- bucket = e - 3;
- // If nothing in hash bucket right now,
- // request more memory from the system.
- if (nextf[bucket] == NULL)
- morecore(bucket);
- if ((p = (union overhead *)nextf[bucket]) == NULL)
- return (NULL);
- // remove from linked list
- nextf[bucket] = p->ov_next;
- p->ov_magic = MAGIC;
- p->ov_index = bucket;
- #ifdef MSTATS
- nmalloc[bucket]++;
- #endif
- return ((void *)(p + 1));
- }
-
- /*
- * Allocate more memory to the indicated bucket.
- */
- static void morecore(register short bucket)
- {
- register union overhead *op;
- register short rnu; /* 2^rnu bytes will be requested */
- register short nblks; /* become nblks blocks of the desired size */
- register short siz;
-
- if (nextf[bucket])
- return;
- if (bucket > 11)
- {
- nblks = 1;
- rnu = bucket + 3;
- }
- else
- {
- nblks = 1 << (11 - bucket);
- rnu = 14;
- }
- op = (union overhead *)true_get_memory((size_t)(1 << rnu)
- + (size_t)(nblks) * sizeof(union overhead));
- if (op == NULL)
- return;
- // Add new memory allocated to that on
- // free list for this hash bucket.
- nextf[bucket] = op;
- siz = (1 << (bucket + 3)) + sizeof(union overhead);
- while (--nblks > 0) {
- op->ov_next = (union overhead *)((char *)op + siz);
- op = (union overhead *)((char *)op + siz);
- }
- op->ov_next = NULL;
- }
-
- /* Allocate a large lump of memory, and remember it in a linked
- list so that it can be disposed later.
- Rev Apr 95, go for tempmem (requires sys 7) before giving up. */
- static void *true_get_memory(size_t size)
- {
- MemoryLinks *new, *old;
-
- size += sizeof(MemoryLinks);
- if (!(new = (MemoryLinks *)NewPtr((long)size)))
- {
- // try for tempmem before giving up
- Handle tempHandle;
- OSErr err;
-
- tempHandle = TempNewHandle(size, &err);
- if (err == noErr)
- {
- HLock(tempHandle);
- new = (MemoryLinks *)(*tempHandle);
- new->flags = 1; // using temp mem
- }
- else
- return(NULL);
- }
- else
- new->flags = 0; // not using temp mem
- old = THeadPtr->next; /* true next or THead itself */
- old->prev = new;
- new->next = old;
- new->prev = THeadPtr;
- THeadPtr->next = new;
- return((void *)(new + 1)); /* user doesn't "see" the links */
- }
-
- void Ffree(void *cp)
- {
- short bucket;
- union overhead *op;
-
- if (cp == NULL)
- return;
- op = (union overhead *)((char *)cp - sizeof (union overhead));
- if (op->ov_magic != MAGIC) {
- return; /* sanity */
- }
- bucket = op->ov_index;
- op->ov_next = nextf[bucket];
- nextf[bucket] = op;
- #ifdef MSTATS
- nmalloc[bucket]--;
- #endif
- }
-
- /*
- * When a program attempts "storage compaction" as mentioned in the
- * old malloc man page, it realloc's an already freed block. Usually
- * this is the last block it freed; occasionally it might be farther
- * back. We have to search all the free lists for the block in order
- * to determine its bucket: 1st we make one pass thru the lists
- * checking only the first block in each; if that fails we search
- * ``reall_srchlen'' blocks in each list for a match (the variable
- * is extern so the caller can modify it). If that fails we just copy
- * however many bytes was given to realloc() and hope it's not huge.
- */
- short reall_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
-
- void *Frealloc(void *cp, size_t nbytes)
- {
- register size_t onb;
- union overhead *op;
- char *res;
- register short i;
- short was_alloced = 0;
-
- if (cp == NULL)
- return (Fmalloc(nbytes));
- if (!nbytes)
- {
- Ffree(cp);
- return(NULL);
- }
- op = (union overhead *)((char *)cp - sizeof (union overhead));
- if (op->ov_magic == MAGIC) {
- was_alloced++;
- i = op->ov_index;
- } else {
- /*
- * Already free, doing "compaction".
- *
- * Search for the old block of memory on the
- * free list. First, check the most common
- * case (last element free'd), then (this failing)
- * the last ``reall_srchlen'' items free'd.
- * If all lookups fail, then assume the size of
- * the memory block being realloc'd is the
- * smallest possible.
- */
- if ((i = findbucket(op, 1)) < 0 &&
- (i = findbucket(op, reall_srchlen)) < 0)
- i = 0;
- }
- onb = (1 << (i + 3));
- /* avoid the copy if same size block */
- if (was_alloced &&
- nbytes <= onb && nbytes > (onb >> 1) ) {
- return(cp);
- }
- if ((res = Fmalloc(nbytes)) == NULL)
- return (NULL);
- if (cp != res) /* common optimization */
- BlockMove ((Ptr)cp, (Ptr)res, (Size)((nbytes < onb) ? nbytes : onb));
- if (was_alloced)
- Ffree(cp);
- return (res);
- }
-
- /*
- * Search ``srchlen'' elements of each free list for a block whose
- * header starts at ``freep''. If srchlen is -1 search the whole list.
- * Return bucket number, or -1 if not found.
- */
- static short findbucket(union overhead *freep, short srchlen)
- {
- register union overhead *p;
- register short i, j;
-
- for (i = 0; i < NBUCKETS; i++) {
- j = 0;
- for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
- if (p == freep)
- return (i);
- j++;
- }
- }
- return (-1);
- }
-
- #ifdef MSTATS
- /*
- * mstats - print out statistics about malloc
- *
- * Prints two lines of numbers, one showing the length of the free list
- * for each size category, the second showing the number of mallocs -
- * frees for each size category.
- */
- void mstats(char *s);
- void mstats(char *s)
- {
- register short i, j;
- register union overhead *p;
- short totfree = 0,
- totused = 0;
-
- fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
- for (i = 0; i < NBUCKETS; i++) {
- for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
- ;
- fprintf(stderr, " %d", j);
- totfree += j * (1 << (i + 3));
- }
- fprintf(stderr, "\nused:\t");
- for (i = 0; i < NBUCKETS; i++) {
- fprintf(stderr, " %d", nmalloc[i]);
- totused += nmalloc[i] * (1 << (i + 3));
- }
- fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
- totused, totfree);
- }
- #endif
-
- /* list wraps around */
- void FFreeAll(void)
- {
- MemoryLinks *dump = THeadPtr->next, *nextOne;
- Handle tempHandle;
-
- while (dump != THeadPtr)
- {
- nextOne = dump->next;
- //dump->flags = 1 means using temp mem
- if (dump->flags & 1)
- {
- tempHandle = RecoverHandle((Ptr)dump);
- if (MemError() == noErr)
- DisposeHandle(tempHandle);
- }
- else // just a regular pointer
- DisposePtr((Ptr)dump);
- dump = nextOne;
- }
- }
-
-
- /* Misc */
-
- void NullOut(char *str, long nBytes)
- {
- register long i;
-
- i = nBytes;
- while (--i >= 0)
- *str++ = '\0';
- }
-
- /* Check for the generic "Command<period>" that signals a
- wish to stop. */
- Boolean TaskWasInterrupted()
- {
- EventRecord event;
- long thisTime;
- Boolean gotEvent;
- static long lastTime;
-
- Delay(0L, &thisTime);
- if (thisTime - lastTime < 60L) return(FALSE);
- lastTime = thisTime;
- SystemTask();
- gotEvent = GetNextEvent(62, &event);
- if (gotEvent) /* see if interrupt */
- {
- switch (event.what)
- {
- case keyDown:
- case autoKey:
- /* look for abort key (Command-<period>) */
- if ((event.modifiers & cmdKey)
- && ((event.message & charCodeMask) == '.'))
- {
- return(TRUE);
- }
- break;
- default:
- break;
- } /* switch */
- }
- return(FALSE);
- }
-
- /* Check for events 15 times a second, allow hAWK to run for
- at most 12 ticks if no event. Return control to calling
- app's event loop, so that hAWK can run at the same time
- as calling app without too much slowdown. Return TRUE
- if interrupted, FALSE if should continue. */
- Boolean CheckInWithCallingApp()
- {
- EventRecord event;
- long thisTime;
- Boolean gotEvent;
- static long lastTime, tickAlong;
-
- Delay(0L, &thisTime);
- if (thisTime < tickAlong) return(FALSE);
- tickAlong = thisTime + 4L;
-
- if ((gotEvent = EventAvail(everyEvent, &event))
- || thisTime - lastTime > 12L)
- {
- if (gotEvent)
- {
- switch (event.what)
- {
- case keyDown:
- case autoKey:
- /* look for abort key (Command-<period>) */
- if ((event.modifiers & cmdKey)
- && ((event.message & charCodeMask) == '.'))
- {
- GetNextEvent(62, &event);
- return(TRUE);
- }
- break;
- default:
- break;
- } /* switch */
- }
- else
- lastTime = thisTime;
- DoEventLoopOnce();
- }
- return(FALSE);
- }
-